package net.wanglu.www.zzz.rule.sva;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Pattern;

import net.wanglu.www.zzz.rule.BadEgg;
import net.wanglu.www.zzz.rule.Rule;
import net.wanglu.www.zzz.service.se.nsubj._NSubjTuple;
import edu.stanford.nlp.ling.TaggedWord;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.TreeGraphNode;

public class CollectiveNounAsSubj extends _SvaRule {
	
	public static Pattern UnmarkedPluralNouns = Pattern.compile("\\bcattle\\b|\\bcavalry\\b|\\bChinese\\b|\\bchorus\\b|\\bclergy\\b|\\belite\\b|\\bEnglish\\b|\\bfashion\\b|\\bfolk\\b|\\bforce\\b|\\bgentry\\b|\\bintelligentsia\\b|\\bJapanese\\b|\\bkindred\\b|\\blaity\\b|\\blivestock\\b|\\bmilitia\\b|\\bnobility\\b|\\bpeasantry\\b|\\bpeoples?\\b|\\bpolice\\b|\\bposse\\b|\\bpoultry\\b|\\brabble\\b|\\briffraff\\b|\\bvermin\\b|\\bswine\\b",Pattern.CASE_INSENSITIVE);
	
	public static Pattern WholePluralNouns = Pattern.compile("\\barmy\\b|\\baudience\\b|\\bband\\b|\\bboard\\b|\\bcabinet\\b|\\bcavalry\\b|\\bchoir\\b|\\bclass\\b|\\bclub\\b|\\bcommittee\\b|\\bcompany\\b|\\bcongregation\\b|\\bconuncil\\b|\\bcrew\\b|\\bcrowd\\b|\\benemy\\b|\\bfamily\\b|\\bfleet\\b|\\bfoot\\b|\\bgang\\b|\\bgeneration\\b|\\bgovernment\\b|\\bgroup\\b|\\bhorse\\b|\\binfantry\\b|\\bjury\\b|\\bmanagement\\b|\\bmob\\b|\\bnavy\\b|\\boffspring\\b|\\bopposition\\b|\\bparty\\b|\\bpopulation\\b|\\bpublic\\b|\\bstaff\\b|\\bteam\\b|\\byouth\\b",Pattern.CASE_INSENSITIVE);
	public static Pattern DTWholePluralNouns = Pattern.compile("(\\ba\\b|\\ban\\b|\\beach\\b|\\bevery\\b|\\bthis\\b|\\bthat\\b) (\\barmy\\b|\\baudience\\b|\\bband\\b|\\bboard\\b|\\bcabinet\\b|\\bcavalry\\b|\\bchoir\\b|\\bclass\\b|\\bclub\\b|\\bcommittee\\b|\\bcompany\\b|\\bcongregation\\b|\\bconuncil\\b|\\bcrew\\b|\\bcrowd\\b|\\benemy\\b|\\bfamily\\b|\\bfleet\\b|\\bfoot\\b|\\bgang\\b|\\bgeneration\\b|\\bgovernment\\b|\\bgroup\\b|\\bhorse\\b|\\binfantry\\b|\\bjury\\b|\\bmanagement\\b|\\bmob\\b|\\bnavy\\b|\\boffspring\\b|\\bopposition\\b|\\bparty\\b|\\bpopulation\\b|\\bpublic\\b|\\bstaff\\b|\\bteam\\b|\\byouth\\b)",Pattern.CASE_INSENSITIVE);

	public static Pattern TheCollectiveNoun = Pattern.compile("\\bbourgeoisie\\b|\\bcast\\b|\\bcity\\b|\\bcollege\\b|\\bcommunity\\b|\\bcountry\\b|\\bfactory\\b|\\bhumanity\\b|\\bmankind\\b|\\bproletariat\\b|\\bschool\\b|\\btown\\b|\\buniversity\\b|\\bvillage\\b|\\bworld\\b", Pattern.CASE_INSENSITIVE);
	public static Pattern StartWithThe = Pattern.compile("^\\bThe\\b");

	public static Pattern ClassCollectiveNoun = Pattern.compile("\\bclothing\\b|\\bcrockery\\b|\\bfoliage\\b|\\bfurniture\\b|\\bluggage\\b|\\bbaggage\\b|\\bmachinery\\b|\\bmerchandise\\b|\\bpoetry\\b", Pattern.CASE_INSENSITIVE);
	
	public int UnmarkedPlural = 1;
	public int WholePlural = 2;
	public int DTWholePlural = 4;
	public int TheCollective = 8;
	public int ClassCollective = 16;
	
	@Override
	public Object applicable(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		if ( super.applicable(objects) == Rule.Inapplicable) return Rule.Inapplicable;
		_NSubjTuple nst = (_NSubjTuple) objects[1];
		if ( !"NP".equals(nst.getSubjectAncestor().value())) return Rule.Inapplicable;
		return Rule.Applicable;
	}

	@Override
	public Object deviseRightSolution(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object examine(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		HashMap<?, ?> preprocessData = (HashMap<?, ?>) objects[0];
		_NSubjTuple nst =  (_NSubjTuple) objects[1];
		
		if ( this.applicable(preprocessData, nst) == Rule.Inapplicable) return Rule.Inapplicable;
		Tree subjAncestor = nst.getSubjectAncestor();
		TreeGraphNode subj = (TreeGraphNode) nst.getSubj();
		TreeGraphNode verb = (TreeGraphNode) nst.getVerb();
		TreeGraphNode cop = (TreeGraphNode) nst.getCop();
		TreeGraphNode closestAux = (TreeGraphNode) nst.getAux();
		
		TreeGraphNode pred = verb;
		if ( cop != null) pred = cop;
		if ( closestAux != null) pred = closestAux;
		String predWord = pred.label().word();
		String predTag = pred.label().tag();
		
		ArrayList<TaggedWord> twl = subjAncestor.taggedYield();
		sb.clear();
		for ( TaggedWord tw : twl) {
			sb.append(tw.word()).append(" ");
		}
		String subjWord = subj.label().word();
		
		if ( StartWithThe.matcher(sb.toString()).find() && TheCollectiveNoun.matcher(subjWord).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setFlag(this.TheCollective);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}
		} else if ( ClassCollectiveNoun.matcher(subjWord).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setFlag(this.ClassCollective);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}
		} else if ( UnmarkedPluralNouns.matcher(subjWord).find()) {
			if (Rule.PluralVerb.matcher(predTag).find() && !"was".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setFlag(this.UnmarkedPlural);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}											
		} else if ( WholePluralNouns.matcher(subjWord).find()) {
			if ( DTWholePluralNouns.matcher(sb.toString()).find()) {
				if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
					return null;
				} else {
					BadEgg egg = new BadEgg();
					egg.setFlag(this.DTWholePlural);
					egg.setViolatedRule(this);
					egg.whereIsWrong = nst;
					return egg;
				}
			}
		} 
	
		return Rule.Inapplicable;
	}

	@Override
	public Object whyItsWrong(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		BadEgg egg = (BadEgg) objects[0];
		sb.clear();
		if ( egg.getFlag() == this.UnmarkedPlural) {
			sb.append("<p>");
			sb.append("某些集体名词形式上是单数，但它们的谓语动词一般用复数，这些词称之为无标记复数名词。这些名词有：cattle, cavalry, Chinese, chorus, clergy, elite, English, fashion, folk, force, gentry, intelligentsia, Japanese, kindred, laity, livestock, militia, nobility, peasantry, people, police, posse, poultry, rabble, riffraff, vermin, youth, swine等。");
			sb.append("</p>");
		} else if ( egg.getFlag() == this.DTWholePlural) {
			sb.append("<p>");
			sb.append("有些具有生命意义的集体名词作主语时，如被看成一个整体，谓语动词用单数；如被看成组成该集体的一个个成员，则谓语动词用复数形式。这类名词有：army, audience, band, board, cabinet, cavalry, choir, class, club, committee, company, congregation, conuncil, crew, crowd, enemy, family, fleet, foot, gang, generation, government, group, horse, infantry, jury, management, mob, navy, offspring, opposition, party, population, public, staff, team, youth等。");
			sb.append("</p>");
			sb.append("<p>");
			sb.append("但这些集体名词被具有单数意义的限定词a, an, each, every, this, that");
			sb.append("</p>");
		} else if ( egg.getFlag() == this.TheCollective) {
			sb.append("<p>");
			sb.append("有些名词常与the连用，并具有集体意义，但谓语动词一般采用单数形式，这类名词有：bourgeoisie, cast, city, college, community, country, factory, humanity, mankind, proletariat, school, town, university, village, world。");
			sb.append("</p>");			
		} else if ( egg.getFlag() == this.ClassCollective) {
			sb.append("<p>");
			sb.append("某些集体名词是某种东西的总称，只用单数（但不可加不定冠词），所以只与单数形式的动词连用；如果要表示数量的多少，只能用much和little，而不能用many和few来修饰。这类名词有：clothing, crockery, foliage, furniture, luggage, baggage, machinery, merchandise, poetry。");
			sb.append("</p>");			
		}
		return sb.toString();
	}
}
